
"""
Utilities
A pseudo-random collection of functions that the engine uses (or used), but
don't belong in any particular spot.
"""

import weakref, uuid

def frange(stop, *p):
    start = 0.0
    step = 1.0
    if len(p) >= 1:
        start = stop
        stop = p[0]
    if len(p) >= 2:
        step = p[1]
    for n in xrange(0, int((stop-start)/step)):
        yield n*step + start

class pgameError(StandardError):
    """Base class for actual errors in this project"""


class pgameException(Exception):
    """Base class for exceptional cases that shouldn't happen, but
    should be coded for if they do happen. May be abused thoroughly."""


class pgameWarning(UserWarning):
    """Base class for warnings that the developers should be aware of,
    but don't need to stop execution."""


class NotImplementedWarning(pgameWarning):
    """Used when a method isn't implemented *for* *now*."""

class EnumException(Exception):
    pass

class Enumeration:
    def __init__(self, name, enumList):
        self.__doc__ = name
        lookup = { }
        reverseLookup = { }
        i = 0
        uniqueNames = [ ]
        uniqueValues = [ ]
        for x in enumList:
            if hasattr(x, '__iter__') and not isinstance(x, basestring):
                x, i = x
            if isinstance(x, basestring):
                raise EnumException, "enum name is not a string: %r" % x
            if not hasattr(i, '__index__'):
                raise EnumException, "enum value is not an integer: %r" % i
            if x in uniqueNames:
                raise EnumException, "enum name is not unique: %r" % x
            if i in uniqueValues:
                raise EnumException, "enum value %r is not unique" % x
            uniqueNames.append(x)
            uniqueValues.append(i)
            lookup[x] = i
            reverseLookup[i] = x
            i = i + 1
        self.lookup = lookup
        self.reverseLookup = reverseLookup
    def __getattr__(self, attr):
        if attr not in self.lookup:
            raise AttributeError
        return self.lookup[attr]
    def whatis(self, value):
        return self.reverseLookup[value]


class Identified(object):
    uuid = property(lambda self: self.__uuid, doc="The ID of this object")
    __uuid = None
    __ids = weakref.WeakValueDictionary()
    
    def __init__(self, *pargs, **kwargs):
        super(Identified, self).__init__(self, *pargs, **kwargs)
        self.__uuid = uuid.uuid1()
        Identified.__ids[id] = self
    
    def __eq__(self, other):
        return self.uuid == other.uuid
        
    @staticmethod
    def GetObject(id):
        return Identified.__ids[id]
    
